#define DEBUG
#include <cstdio>
#include <cstring>

using namespace std;

const int maxn=50000, maxk=15;

int min(int a, int b) {
  return a<b ? a : b;
}

int max(int a, int b) {
  return a>b ? a : b;
}

class SegmentTree {
public:
  int minv[4*maxn+1], maxv[4*maxn+1], up[4*maxn+1], down[4*maxn+1], mark[4*maxn+1];

  static int fup(int minl, int maxl, int minr, int maxr) {
    return maxl-minr;
  }

  static int fdown(int minl, int maxl, int minr, int maxr) {
    return maxr-minl;
  }

  void merge(int o) {
    minv[o] = min(minv[o*2], minv[o*2+1]);
    maxv[o] = max(maxv[o*2], maxv[o*2+1]);
    up[o] = max(max(up[o*2], up[o*2+1]), fup(minv[o*2], maxv[o*2], minv[o*2+1], maxv[o*2+1]));
    down[o] = max(max(down[o*2], down[o*2+1]), fdown(minv[o*2], maxv[o*2], minv[o*2+1], maxv[o*2+1]));
  }

  void init(int o, int l, int r, int a[]) {
    if (l==r) {
      minv[o]=maxv[o]=a[l];
      up[o]=down[o]=mark[o] = 0;
    } else {
      int mid=(l+r)/2;
      init(o*2, l, mid, a), init(o*2+1, mid+1, r, a);
      merge(o);
    }
  }

  void markDown(int o, int l, int r) {
    if (mark[o]) {
      if (l!=r) {
        mark[o*2]+=mark[o], mark[o*2+1]+=mark[o];
      }
      minv[o]+=mark[o], maxv[o]+=mark[o];
      mark[o]=0;
    }
  }

  void add(int o, int l, int r, int tl, int tr, int tv) {
    markDown(o, l, r);
    if (l==tl && r==tr) {
      mark[o] += tv;
      markDown(o, l, r);
    } else {
      int mid=(l+r)/2;
      if (tl<=mid) {
        add(o*2, l, mid, max(tl, l), min(tr, mid), tv);
      } else {
        markDown(o*2, l, mid);
      }
      if (tr>mid) {
        add(o*2+1, mid+1, r, max(tl, mid+1), min(tr, r), tv);
      } else {
        markDown(o*2+1, mid+1, r);
      }
      merge(o);
    }
  }

  int get(int o, int l, int r, int tl, int tr, int &mint, int &maxt, int f(int, int, int, int)) {
    markDown(o, l, r);
    if (l==tl && r==tr) {
      mint=minv[o], maxt=maxv[o];
      return f(0, up[o], 0, down[o]);
    } else {
      int mid=(l+r)/2, ret=0, minl, minr, maxl, maxr;
      if (tl<=mid && tr>mid) {
        ret = max(ret, get(o*2, l, mid, max(tl, l), min(tr, mid), minl, maxl, f));
        ret = max(ret, get(o*2+1, mid+1, r, max(tl, mid+1), min(tr, r), minr, maxr, f));
        ret = max(ret, f(minl, maxl, minr, maxr));
        mint = min(minl, minr), maxt=max(maxl, maxr);
      } else if (tl<=mid) {
        ret = max(ret, get(o*2, l, mid, max(tl, l), min(tr, mid), mint, maxt, f));
      } else if (tr>mid) {
        ret = max(ret, get(o*2+1, mid+1, r, max(tl, mid+1), min(tr, r), mint, maxt, f));
      }
      return ret;
    }
  }
};

class Tree {
public:
  SegmentTree sgt;
  int n, m, ind[maxn+1], to[2*maxn-1], link[2*maxn-1], top[maxn+1], son[maxn+1], dfn[maxn+1], dep[maxn+1], f[maxn+1][maxk+1], size[maxn+1];

  void addSide(int u, int v) {
    m++;
    to[m] = v;
    link[m] = ind[u];
    ind[u] = m;
  }

  void dfs1(int o, int fa) {
    dep[o] = dep[fa]+1;
    f[o][0] = fa;
    size[o] = 1;
    for (int i=ind[o]; i; i=link[i]) {
      if (to[i]!=fa) {
        dfs1(to[i], o);
        size[o] = size[to[i]]+1;
      }
    }
  }

  void dfs2(int o) {
    dfn[o] = ++dfn[0];
    son[o] = 0;
    for (int i=ind[o]; i; i=link[i]) {
      if (to[i]!=f[o][0]) {
        if (size[son[o]]<size[to[i]]) {
          son[o] = to[i];
        }
      }
    }
    if (son[o]) {
      top[son[o]] = top[o];
      dfs2(son[o]);
    }
    for (int i=ind[o]; i; i=link[i]) {
      if (to[i]!=f[o][0] && to[i]!=son[o]) {
        top[to[i]] = to[i];
        dfs2(to[i]);
      }
    }
  }

  void build() {
    dfs1(1, 0);
    top[1] = 1;
    dfs2(1);

    for (int j=1; j<=maxk; j++) {
      for (int i=1; i<=n; i++) {
        f[i][j] = f[f[i][j-1]][j-1];
      }
    }
  }

  int lca(int u, int v) {
    if (dep[u]<dep[v]) {
      int t;
      t=u, u=v, v=t;
    }
    for (int i=maxk; i>=0; i--) {
      if (dep[f[u][i]]>=dep[v]) {
        u = f[u][i];
      }
    }
    if (u==v) {
      return u;
    }
    for (int i=maxk; i>=0; i--) {
      if (f[u][i]!=f[v][i]) {
        u = f[u][i], v = f[v][i];
      }
    }
    return f[u][0];
  }

  int get(int s, int t, int &minv, int &maxv, int fun(int, int, int, int)) {
    int ret=0, mint, maxt;
    if (dep[top[s]]<=dep[t]) {
      return sgt.get(1, 1, n, dfn[t], dfn[s], minv, maxv, fun);
    } else {
      ret = sgt.get(1, 1, n, dfn[top[s]], dfn[s], minv, maxv, fun);
      s = f[top[s]][0];
    }
    for (; dep[top[s]]>dep[t]; s=f[top[s]][0]) {
      ret = max(ret, sgt.get(1, 1, n, dfn[top[s]], dfn[s], mint, maxt, fun));
      ret = max(ret, fun(mint, maxt, minv, maxv));
      minv = min(mint, minv), maxv = max(maxt, maxv);
    }
    ret = max(ret, sgt.get(1, 1, n, dfn[t], dfn[s], mint, maxt, fun));
    ret = max(ret, fun(mint, maxt, minv, maxv));
    minv = min(mint, minv), maxv = max(maxt, maxv);
    return ret;
  }

  void add(int s, int t, int tv) {
    for (; dep[top[s]]>dep[t]; s=f[top[s]][0]) {
      sgt.add(1, 1, n, dfn[top[s]], dfn[s], tv);
    }
    sgt.add(1, 1, n, dfn[t], dfn[s], tv);
  }
};

int main() {
  freopen("travel.in", "r", stdin);
  freopen("travel.out", "w", stdout);

  static int p[maxn+1];
  int n;
  scanf("%d", &n);
  for (int i=1; i<=n; i++) {
    scanf("%d", p+i);
  }

  static Tree tree;
  tree.n = n;
  for (int i=1; i<n; i++) {
    int x, y;
    scanf("%d %d", &x, &y);
    tree.addSide(x, y);
    tree.addSide(y, x);
  }
  tree.build();
  static int tmp[maxn+1];
  for (int i=1; i<=n; i++) {
    tmp[tree.dfn[i]] = p[i];
  }
  tree.sgt.init(1, 1, n, tmp);

  int q;
  scanf("%d", &q);
  for (int i=1; i<=q; i++) {
    int a, b, v, t, minl, maxl, minr, maxr, ans=0;
    scanf("%d %d %d", &a, &b, &v);
    t=tree.lca(a, b);
    ans = max(tree.get(a, t, minr, maxr, SegmentTree::fup), tree.get(b, t, minl, maxl, SegmentTree::fdown));
    ans = max(ans, SegmentTree::fup(minl, maxl, minr, maxr));
    printf("%d\n", ans);
    tree.add(a, t, v), tree.add(b, t, v), tree.add(t, t, -v);
  }

  fclose(stdin);
  fclose(stdout);
  return 0;
}
